package se.ytterman.jpcap.framework.factory;

import java.lang.*;
import java.util.*;

import javax.xml.xpath.*;
import org.w3c.dom.*;
import org.xml.sax.InputSource;

import se.ytterman.jpcap.framework.system.SystemConfiguration;
import se.ytterman.jpcap.util.InstanceFactory;

public class RequestFactory {
    
    public static void parseRequestConfiguration(InputSource inputSource) {
	try {
	    // Create Xpath factory instance
	    XPathFactory xpathFactory = XPathFactory.newInstance();

	    // Create an Xpath object
	    XPath xPath = xpathFactory.newXPath();

	    // Create a nodeset of variable groups
	    String requestPartstExtractor = "/ProtocolConfiguration[@version=\"1.0\"]" +
                                            "/Protocol[@version=\"1.0\"]" +
		                            "/Requests/Request/RequestFormat/RequestPart";

	    NodeList requestParts = (NodeList) xPath.evaluate(requestPartstExtractor,
							      inputSource,
							      XPathConstants.NODESET);

	    int partcount = requestParts.getLength();

	    if(false)
		System.out.println("Request nodes: " + partcount);

	    // Iterate over request parts
	    for(int i = 0; i < partcount; i ++) {
		// Fetch request part
		Node partNode = requestParts.item(i);

		// Fetch identifying name of part
		String partName = xPath.evaluate("@name", partNode);

		// Fetch human-readable description of the part
		String partDecription = xPath.evaluate("@description", partNode);
		
		// Fetch the node describing Java class and constructor variables
		Node producerNode = (Node) xPath.evaluate("ProducerClass", 
							  partNode,
							  XPathConstants.NODE);
		
		// Fetch the "binary name" of the Java class
		// This will be used to load the class and create an instance
		String producerClass = xPath.evaluate("@name", producerNode);

		// Extract constructor parameters ("simple" types)
		NodeList valueNodes = (NodeList) xPath.evaluate("ConstructorParameters/Value", 
								 producerNode,
								 XPathConstants.NODESET);

		int valuecount = valueNodes.getLength();
		Object[] constructorParameters = new Object[valuecount];
		Object o = null;

		// Iterate over all constructor values descibed in the XML file
		// Build a String array to match with the producer class constructor 
		// signature
		for(int j = 0; j < valuecount; j++) {
		    // Extract node from DOM tree
		    Node valueNode = valueNodes.item(j);

		    // Create "array" as constructor argument 
		    // One instance created from one XML string (Value tag tex payload) 
		    Object[] valueArray = new Object[1];

		    // Extract value and attributes
		    String valueType = xPath.evaluate("@type", valueNode);

		    // Check if it's a static type
		    if(valueType.compareTo("static") == 0) {
			// Handle static values
			String dataType = xPath.evaluate("@datatype", valueNode);
			String dataValue = valueNode.getTextContent();

			// Assign to array
			valueArray[0] = dataValue;

			// Create instance of constructor parameter and add to to 
			// signature paramater array
			constructorParameters[j] = InstanceFactory.newInstance(dataType, valueArray, false);

			// Create an instance of the frame part producer class 
			o = InstanceFactory.newInstance(producerClass, constructorParameters, false);
		    }

		    // Check if it's a reference type
		    if(valueType.compareTo("reference") == 0) {
			// Handle reference values
			String dataType = xPath.evaluate("@datatype", valueNode);
			String dataKey = valueNode.getTextContent();

			// Fetch a reference to an instace of system data
			o = SystemConfiguration.getSystemProperty(dataKey);
		    }
		    
		    // XXX 
		    System.out.println(partName + " = " + o);
		}
	    }
	}
	catch(Exception e) {
	    System.out.println(e + " : " + e.getMessage());
	}
    }
}

